/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package fr.ove.openmath.jome.formaters.om;

/**
 *
 * @author Mr.Sam
 */
import fr.ove.utils.*;
import fr.ove.openmath.jome.model.*;
import fr.ove.openmath.jome.formaters.om.*;

/**
* Formats the formula tree structure as its corresponding OpenMath object.<BR>
* This is the formater of operators which have the sigma format :
*
* @author © 2000 DIRAT Laurent
* @version 1.0 21/02/2000
*/
public class MapsToSigmaFormater implements Formater {
    /**
    * Returns the specified object formatted as a string.
    * @param formatedObject the formatted object (for structured object, could represents the beginning).
    * @param formaterRepository where the different other formaters are.
    * @param obj the object to format.
    */
    public String format(String formatedObject, FormaterRepository formaterRepository, Object obj) {
        OpenMathFormater omFormater = (OpenMathFormater) formaterRepository;
        FormulaTreeStructure fts = (FormulaTreeStructure) obj;
        
        Formater formater;
        
        String objectId = fts.getResourceIdentifier();
        
        // Si le nbre de fils est 3, alors a priori, on a un sigma sémantiquement juste (vis à vis OM au moins)
        if (fts.getNbChildren() == 3) {
            // Pour facilité de manip, on récupère les fils des slots, i.e. les éléments du sigma
            FormulaTreeStructure argument = (FormulaTreeStructure) fts.getChild(0).getChild(0);
            FormulaTreeStructure lowerBound = (FormulaTreeStructure) fts.getChild(1).getChild(0);
            FormulaTreeStructure upperBound = (FormulaTreeStructure) fts.getChild(2).getChild(0);
            // Si lowerBound n'est pas de la forme var = integer, alors on n'a pas un sigma sémantiquement juste
            // (vis à vis OM au moins).
            // Si c'est le cas, on récupère var, qui va être la variable liée pour le bind de la fonction, et 
            // integer, qui va être la borne inf de l'intervalle pour la syntaxe OM
            if ((lowerBound.isOperator() && ((Operator) lowerBound).getTheOperator().equals("="))) {
                if (lowerBound.getNbChildren() == 2) {
                    FormulaTreeStructure child0 = (FormulaTreeStructure) lowerBound.getChild(0);
                    FormulaTreeStructure child1 = (FormulaTreeStructure) lowerBound.getChild(1);
                    if (child0.getResourceIdentifier().equals("VARIABLE")/* && child1.getResourceIdentifier().equals("INTEGER")*/) {
                        //if (upperBound.getResourceIdentifier().equals("INTEGER")) {
                            // A ce stade, tout colle pourqu'il y ait un objet OM 
                            formatedObject += omFormater.writeStartApplication();
                            // On récupère le nom du symbole
                            formatedObject += omFormater.writeSymbol(objectId);
                            // Création de l'integer_interval nécessaire
                            formatedObject += omFormater.writeStartApplication();
                            formatedObject += omFormater.writeSymbol("interval", "integer_interval");
                            
                            objectId = child1.getResourceIdentifier();
                            formater = formaterRepository.getFormater(objectId);
                            formatedObject = formater.format(formatedObject, formaterRepository, child1);
                            // On sait que child1 et upperBound sont tous les 2 des entiers et ont donc
                            // le même formatteur
                            
                            objectId = upperBound.getResourceIdentifier();
                            formater = formaterRepository.getFormater(objectId);
                            
                            formatedObject = formater.format(formatedObject, formaterRepository, upperBound);
                            
                            formatedObject += omFormater.writeEndApplication();
                            
                            // Création du bind
                            formatedObject += omFormater.writeStartBinding();
                            formatedObject += omFormater.writeSymbol("lambda");
                            
                            // On met la variable liée.
                            formatedObject += omFormater.writeStartBoundVariables();
                            
                            objectId = child0.getResourceIdentifier();
                            formater = formaterRepository.getFormater(objectId);
                            formatedObject = formater.format(formatedObject, formaterRepository, child0);
                            
                            formatedObject += omFormater.writeEndBoundVariables();
                            
                            // On met maintenant l'objet du bind, i.e. l'argument.
                            objectId = argument.getResourceIdentifier();
                            formater = formaterRepository.getFormater(objectId);
                            formatedObject = formater.format(formatedObject, formaterRepository, argument);
                            
                            formatedObject += omFormater.writeEndBinding();
                            formatedObject += omFormater.writeEndApplication();
                        //}
                    }
                }
            }
        }
        
        return formatedObject;
    }
}